home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / SAT / SAT Invaders sample ƒ / main.p < prev    next >
Encoding:
Text File  |  1993-09-19  |  9.4 KB  |  332 lines  |  [TEXT/PJMM]

  1. {================================================}
  2. {=============== SATInvaders main unit ================}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { SATInvaders is a very simple game demonstrating how to use the Sprite Animation}
  10. { Toolkit. It is intended as a minimal demonstration, without many features and options}
  11. { that the other sample program, HeartQuest, has. No high scores or even score, only}
  12. { one life, doesn't save settings, only one kind of enemy, no special effects like explosions}
  13. { etc. }
  14.  
  15. program SATInvaders;
  16.  
  17.     uses
  18.         TransSkel, SAT, GameGlobals, SoundConst, sPlayer, sEnemy, sShot, sMissile;
  19.  
  20.     var
  21.         soundFlag, plotFastFlag: boolean;
  22.  
  23. { -------------------------------------------------------------------- }
  24. {                                Game driver procedures                                }
  25. { -------------------------------------------------------------------- }
  26.  
  27. { Setup a new level. This is called when the game starts and at each new level.}
  28.     procedure SetupLevel (level: integer);
  29.         var
  30.             p: point;
  31.             i, j: integer;
  32.             sp, oldmp: SpritePtr;
  33.             r: rect;
  34.     begin { SetupLevel }
  35. { Clear the Sprite list }
  36.         sp := sRoot;
  37.         while sp <> nil do
  38.             begin
  39.                 oldmp := sp;
  40.                 sp := sp^.next;
  41.                 KillSprite(oldmp);
  42.             end;
  43.         missileCount := 0; { count variable in mMissile }
  44. { Create all the enemy sprites for the level, depending on the level number. }
  45.         for i := 0 to (level + 1) do
  46.             for j := 0 to (level div 2) + 1 do
  47.                 sp := NewSprite(-3, i * 40 + 2, j * 40 + 0, @HandleEnemy, @SetupEnemy, nil);
  48.  
  49. { Make the player sprite. }
  50.         sp := NewSprite(2, offSizeH div 2, offSizeV - 40, @HandlePlayer, @SetupPlayer, nil);
  51. { Copy BackScreen to OffScreen to erase old sprites. }
  52.         CopyBits(BackScreen^.portbits, offscreen^.portbits, offscreen^.portrect, offscreen^.portrect, srcCopy, nil);
  53.         PeekOffScreen;
  54. {SetPort(GameWind);}
  55. {CopyBits(offScreen^.portBits, GameWind^.portBits, offScreen^.portRect, offScreen^.portRect, srcCopy, nil);}
  56.     end; { SetupLevel }
  57.  
  58. { Start a new game. Initialize level, score, number of lives, and call setuplevel to make the first level. }
  59.     procedure StartGame;
  60.     begin
  61.         Level := 1;
  62.         setuplevel(level);
  63.     end;
  64.  
  65. { Declare forward since we want to call it from MoveIt }
  66.     procedure DoFileMenu (item: integer);
  67.     forward;
  68.  
  69. { This routine is the game driver. It calls RunSAT repeatedly until the game ends or is paused. }
  70. { I also read the keyboard here. This could optionally be moved to the "player object" module. }
  71.  
  72.     procedure MoveIt;
  73.         var
  74.             fr, tr, r: Rect;
  75.             pt: Point;
  76.             h: integer;
  77.             truepos: longint;
  78.             n, x: integer;    { Are these used? }
  79.             t, l: longint;
  80.             truepos32, bredd32: integer; { Some old bugfix that I no longer remember... }
  81.             truepos19, bredd19: integer;
  82.             theEvent: EventRecord; { för att testa musklick }
  83. { To check for key clicks with GetKeys: }
  84.             km: KeyMap;
  85.             ignore: OSerr;
  86.     begin
  87.         stillrunning := true; { A flag that tells whether or not to quit this routine. }
  88.  
  89.         HideCursor; { NOTE: No matter how we leave the MoveIt procedure, we should ShowCursor. }
  90.  
  91. { Main loop! Keep running until the game is paused or ends. }
  92.         while stillrunning = true do
  93.             begin
  94.                 t := TickCount;
  95.  
  96. { Here is the real heart of the loop: call Animator once per loop. It will call all the objects. }
  97.                 RunSAT(plotFastFlag);
  98.  
  99. { All the rest of the main loop is game specific, next level, bonus handling, etc. }
  100.                 if globalspeed.h = 0 then
  101.                     begin
  102.                         downcount := pred(downcount);
  103.                         if downcount <= 0 then
  104.                             begin
  105.                                 globalspeed.h := -lasth;
  106.                                 globalspeed.v := 0;
  107.                                 turnflag := false;
  108.                             end;
  109.                     end
  110.                 else if turnflag then
  111.                     begin
  112.                         downcount := 10;
  113.                         lasth := globalspeed.h;
  114.                         globalspeed.h := 0;
  115.                         globalspeed.v := 3;
  116.                     end;
  117.  
  118.                 if not anymonsters then
  119.                     begin
  120.                         SATSoundShutUp;
  121.                         level := level + 1;
  122.                         setuplevel(level);
  123.                     end; {if not anymonsters}
  124.  
  125. { Check for keys being pressed - but don't allow background processing.}
  126. { If you want background processing, either use GetNextEvent+SystemTask or WaitNextEvent (the modern call).}
  127.                 if GetOSEvent(8, theEvent) then { keydown }
  128.                     if BitAnd(theEvent.modifiers, cmdKey) <> 0 then
  129.                         case char(BitAnd(theEvent.message, charCodeMask)) of
  130.                             'q': 
  131.                                 begin
  132. {StillRunning := false;}
  133.                                     SkelWhoa;
  134. { Do all the things we have to do when we leave MoveIt! }
  135.                                     SATSoundShutUp; { Dispose of sound channel }
  136.                                     flushevents(EveryEvent, 0); { To forget events, like mouse clicks etc. }
  137.                                     ShowCursor;
  138.                                     exit(MoveIt);
  139.                                 end;
  140.                             's': 
  141.                                 begin
  142.                                     DoFileMenu(sound);
  143.                                 end;
  144.                             otherwise
  145.                                 ;
  146.                         end; { case}
  147.  
  148. { Delay, using TickCount so it doesn't matter how fast our Mac is. }
  149.                 while ((TickCount - t) < 3) do
  150.                     ;
  151.             end; { while stillrunning (main loop) }
  152.  
  153. {    SetPort(GameWind);}
  154. {    invalrect(Therect);}
  155.  
  156.         while not SATSoundDone do
  157.             SATSoundEvents; {Wait for last sound to complete}
  158.  
  159.         ShowCursor;
  160.         flushevents(EveryEvent, 0); { To forget events, like mouse clicks etc. }
  161.  
  162.         ReportStr('Sorry, game over.');
  163.  
  164.         SATSoundShutUp; { Dispose of sound channel }
  165.     end; { MoveIt }
  166.  
  167.     procedure GameWindUpdate;
  168.         var
  169.             s: str255;
  170.             r: Rect;
  171.             crsr: CursHandle;
  172.     begin
  173.         crsr := GetCursor(WatchCursor);
  174.         SetCursor(crsr^^);
  175.         if SATDepthChangeTest then
  176.             begin
  177.             end;
  178.         ReleaseResource(handle(crsr));
  179.         InitCursor;
  180.  
  181.         PeekOffScreen;
  182. {SetPort(GameWind);}
  183. {CopyBits(offScreen^.portBits, GameWind^.portBits, offScreen^.portRect, offScreen^.portRect, srcCopy, nil);}
  184.     end;
  185.  
  186. {    Process selection from File menu.}
  187.  
  188.     procedure DoFileMenu (item: integer);
  189.     begin
  190.         case item of
  191.             run: 
  192.                 begin
  193. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  194.                     if not ((OurDepth = 1) or (OurDepth = 4) or (OurDepth = 8)) and plotFastFlag then
  195.                         begin
  196.                             ReportStr('Please uncheck ''Fast animation'' or set the monitor to b/w, 4-bit or 8-bit mode in the Control Panel.');
  197.                             exit(DoFileMenu);
  198.                         end;
  199.                     if SATDepthChangeTest then {Update if necessary}
  200.                         ;
  201.                     StartGame;
  202.                     ShowWindow(gameWind);
  203.                     SelectWindow(gameWind);
  204.                     GameWindUpdate;
  205.                     MoveIt;
  206.                 end;
  207.             sound: 
  208.                 begin
  209.                     soundFlag := not soundFlag;
  210.                     CheckItem(FileMenu, sound, soundFlag);
  211.                     if soundFlag then { Tell the sound package our settings, so we don't have to bother. }
  212.                         SATSoundOn
  213.                     else
  214.                         SATSoundOff;
  215.                 end;
  216.             fastAnimation: 
  217.                 begin
  218.                     plotFastFlag := not plotFastFlag;
  219.                     CheckItem(fileMenu, fastAnimation, plotFastFlag);
  220.                 end;
  221.             quit: 
  222.                 SkelWhoa;
  223.         end;
  224.     end;
  225.  
  226.     procedure GameWindIdle;
  227.     begin
  228.         if SATDepthChangeTest then
  229.             begin
  230.                 PeekOffScreen;
  231. {SetPort(GameWind);}
  232. {CopyBits(offScreen^.portBits, gameWind^.portBits, offScreen^.portRect, offScreen^.portRect, srcCopy, nil);}
  233.             end;
  234.     end;
  235.  
  236.     procedure GameWindInit;
  237.     begin
  238. { Tell TransSkel to tell us when to update GameWind. }
  239.         dummy := SkelWindow(GameWind, nil, nil, @GameWindUpdate, nil, nil, nil, @GameWindIdle, false);
  240.  
  241. { Set up the two offscreen GrafPorts "offScreen" and "BackScreen". SAT has a standard}
  242. { way to do this. Let SAT draw the background PICT for us, too. }
  243.  
  244. { Call the init routines for all the sprite units! }
  245.         initEnemy;
  246.         initPlayer;
  247.         initMissile;
  248.         initShot;
  249.  
  250.         ShowWindow(gameWind);
  251.         SelectWindow(gameWind);
  252. { Draw the contents of the window (to give the user something to look at during the rest of startup). }
  253.         PeekOffScreen;
  254. {CopyBits(offscreen^.portbits, GameWind^.portbits, GameWind^.portrect, GameWind^.portrect, srcCopy, nil);}
  255.     end;
  256.  
  257. { -------------------------------------------------------------------- }
  258. {                        Menu handling procedures                        }
  259. { -------------------------------------------------------------------- }
  260.  
  261. {    Handle selection of "About…" item from Apple menu}
  262.  
  263.     procedure DoAbout;
  264.         var
  265.             h: StringHandle;
  266.             ignore: integer;
  267.     begin
  268.         ignore := Alert(aboutAlrt, nil);
  269.     end;
  270.  
  271. {    Initialize menus.  Tell TransSkel to process the Apple menu}
  272. {    automatically, and associate the proper procedures with the}
  273. {    File menu.}
  274.  
  275.     procedure SetUpMenus;
  276.     begin
  277.         SkelApple('About SAT Invaders…', @DoAbout);
  278.         fileMenu := GetMenu(fileMenuRes);
  279.         dummy := SkelMenu(fileMenu, @DoFileMenu, nil, true);
  280. { Set the following flags so they match the menu }
  281.         soundFlag := true;
  282.         plotFastFlag := true;
  283.     end;
  284.  
  285. { Hide gamewindow on suspend, so the user can get access to disk icons etc. }
  286.  
  287.     procedure DoSuspendResume (b: boolean);
  288.     begin
  289.         if b then
  290.             begin
  291.                 showwindow(gameWind);
  292.                 selectwindow(gameWind);
  293.             end
  294.         else
  295.             hidewindow(gameWind)
  296.     end;
  297.  
  298.     function DoEvt (e: eventRecord): boolean;
  299.     begin
  300.         if e.what = OSevt then
  301.             begin
  302.                 if BAND(BROTL(e.message, 8), $FF) = SuspendResumeMessage then
  303.                     DoSuspendResume(BAnd(e.message, 1) <> 0);
  304.                 DoEvt := true;
  305.             end
  306.         else
  307.             DoEvt := false;
  308.     end; (* end DoEvent *)
  309.  
  310. { -------------------------------------------------------------------- }
  311. {                                    Main                                }
  312. { -------------------------------------------------------------------- }
  313.  
  314. begin
  315.     SkelInit(6, nil);                { initialize }
  316.  
  317. { Init all the different parts of the game. }
  318.     SetUpMenus;    { install menu handlers }
  319.     GameWind := InitSAT(129, 128, 512, 322);
  320.  
  321.     GameWindInit;    { Init the game window }
  322.     Loadsounds;        { preload all sound resources }
  323.  
  324. { Set the randseed to something that is random enough. }
  325.     randSeed := TickCount;
  326.  
  327.     SkelEventHook(@DoEvt); { handle MultiFinder-events }
  328.  
  329.     SkelMain;                { loop 'til Quit selected }
  330.     SkelClobber;                { clean up }
  331.     SATSoundShutUp;            { Terminate sounds }
  332. end.